using System;
using System.Threading;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
using System.Diagnostics;
using System.Configuration;
using System.Messaging;
using System.Data.OleDb;
using System.Data;
//using System.Web.Script.Serialization.JavaScriptSerializer;


namespace Derrick.Web
{
    public class SIServer : Server
    {
        ServerInterfaceConfig config;

        public SIServer(ServerInterfaceConfig c)
            : base(Dns.GetHostEntry(IPAddress.Parse(c.BindTo)).AddressList[0], c.Port, c.Authentication)
        {
            config = c;

        }

        public override Response HandleRequest(Request request, DateTime lastUpdate, Client cometClient)
        {
            if (_traceSwitch == null)
            {
                _traceSwitch = new TraceSwitch("TraceLevelSwitch", "Comet Tracing");
            }

            ///TO DO: add in method to send response in JSON
            ///Derrick Lau - Feb. 3, 2012
            //Console.WriteLine("SIServer HandleRequest(). " + request.Url);
            Trace.WriteLine("SIServer HandleRequest(). " + request.Url);

            //Console.WriteLine("---");
            Trace.WriteLine("---");
            //Console.WriteLine("\""+request.Body+"\"");
            Trace.WriteLine("\"" + request.Body + "\"");
            //Console.WriteLine("---");
            Trace.WriteLine("---");

            Trace.WriteLineIf(_traceSwitch.TraceInfo, "Inside SIServer.HandleRequest()...");

            try
            {

                #region Process HTTP message as XML
                //Picks up message from HTTP:
                XmlSerializer s = new XmlSerializer(typeof(SIRequest));

                MemoryStream mem = new MemoryStream();
                mem.Write(System.Text.Encoding.ASCII.GetBytes(request.Body), 0, request.Body.Length);
                mem.Seek(0, 0);

                //Loads message into object for processing.
                SIRequest data = (SIRequest)s.Deserialize(mem);
                #endregion Process HTTP message as XML

                #region Process HTTP message as JSON




                #endregion Process HTTP message as JSON

                //Monitor.Wait(_lockObject);
                //_semaphore.WaitOne();

                //process message, do stuff here!
                //string responseMsg = "<?xml version='1.0'?><Response>";
                //string responseMsg = @"{";
                string responseMsg = String.Empty;

                //add 2 KB for Google chrome:
                //for (int i = 0; i < 2048; i++)
                //{
                //    responseMsg += " ";
                //}


                //foreach (string msg in data.Messages)
                //{
                //    responseMsg += "<Message>" + msg + " at COMET server.</Message>";
                //}

                //lock (_lockObj)
                //{
                //    if (QueueMessage.Instance.LastUpdated > lastUpdate)
                //    {
                
                //if (!String.IsNullOrEmpty(QueueMessage.Instance.Message))
                //{
                //    //responseMsg += "\"Message\":\"" + QueueMessage.Instance.Message + "\"";
                //    responseMsg += QueueMessage.Instance.Message;
                //}
                //else
                //{
                //    responseMsg += "No message.";
                //}
                //    }
                //}

                OleDbConnection conn = new OleDbConnection();
                using (OleDbCommand cmd = new OleDbCommand("select message_id, message from comettest_messages m where message_id not in (select message_id from comettest_tracking where client_id = " + cometClient.ID + ")", conn))
                {
                    cmd.CommandType = System.Data.CommandType.Text;
                    OleDbDataAdapter adapter = new OleDbDataAdapter(cmd);
                    DataTable allMessages = new DataTable();
                    adapter.Fill(allMessages);

                    if (allMessages.Rows.Count == 0)
                    {
                        cometClient.SendMessage = false;
                        Trace.WriteLineIf(_traceSwitch.TraceVerbose, "No message to send for client " + cometClient.ID);
                    }
                    else
                    {
                        responseMsg = allMessages.Rows[0].Field<string>("message");
                        string trackSend = "insert into comettest_tracking (tracking_id, message_id, client_id, last_updated) values (";
                        trackSend += "comettest_tracking_seq.nextval, " + (int)allMessages.Rows[0].Field<Decimal>("message_id") + ", " + cometClient.ID + ", SYSDATE)";
                        cmd.CommandText = trackSend;
                        cmd.ExecuteNonQuery();
                        cometClient.SendMessage = true;
                        Trace.WriteLineIf(_traceSwitch.TraceVerbose, "Sending message [" + responseMsg + "] for client " + cometClient.ID);
                    }

                }
                //responseMsg += "<Message>Unblocked</Message>";
                //responseMsg += "}";
                Trace.WriteLineIf(_traceSwitch.TraceVerbose, "Message to send to client: " + responseMsg);
                Trace.Flush();

                MessageFormat responseFormat;

                if (request.Headers["Content-Type"].Contains("json"))
                {
                    responseFormat = MessageFormat.json;
                }
                else if (request.Headers["Content-Type"].Contains("xml"))
                {
                    responseFormat = MessageFormat.xml;
                }
                else
                {
                    responseFormat = MessageFormat.text;
                }

                return Response.GetHtmlResponse(responseMsg, QueueMessage.Instance.LastUpdated, responseFormat);

            } catch (Exception ex) {
                Console.WriteLine("Error parsing xml: " + ex.Message);
                Trace.WriteLineIf(_traceSwitch.TraceError, "Inside SIServer.HandleRequest().  Exception thrown: " + ex.ToString());
                Trace.Flush();
                return Response.GetHtmlResponse("Error parsing xml: " + ex.Message, QueueMessage.Instance.LastUpdated, MessageFormat.text);
            }
        }

        public override void BroadcastMessage(Object sender, SendMessageEventArgs args)
        {
            //throw new NotImplementedException();
            Trace.WriteLineIf(_traceSwitch.TraceVerbose, "Broadcasting message [" + args.Message + "] to all clients.");

            int numOfClients = clients.Count;
            for (int i = 0; i < numOfClients; i++)
            {
                clients[i].SendResponse(args);
            }
        }



        [XmlRoot("Request")]
        public class SIRequest
        {
            public enum CommandType
            {
                Queue,
                Remove
            }

            public struct MessageData
            {
                public string Message;
            }

            public CommandType Command = CommandType.Queue;
            public string User = "";

            [XmlElement("Message")]
            public string[] Messages;
        }


    }
}
